package pe.com.bn.sach.calculoCuota;


import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;

public class CalculoCuotaIngreso {

	private static Logger log = Logger.getLogger(CalculoCuotaIngreso.class.getName());
	

	public Hashtable CalculoPrestamoCuota(
			double cuotaIni
			,double comisionEvaluacion 
			,double tasaEfectivaAnual
			,int yearPago, int monthPago, int dayPago 
			,double tasaSegDesgravMensual
			,double valorInmueble
			,double tasaSegInmuebleMensual
			,int plazoPago
			,double portes
			,int diaPagoSel
			,int mesesGracia
			,int dobleJulio
			,int dobleDiciembre
			,int finanGraciaAgente
			){
	
		
		ArrayList calculoCuota = null;
		
		calculoCuota = CalculoPrestamoBase(
				cuotaIni
				,comisionEvaluacion 
				,tasaEfectivaAnual
				,yearPago,monthPago,dayPago 
				,tasaSegDesgravMensual
				,valorInmueble
				,tasaSegInmuebleMensual
				,plazoPago
				,portes
				,diaPagoSel
				,mesesGracia
				,dobleJulio
				,dobleDiciembre
				,finanGraciaAgente
				);

		//Ingresando la data para el Costo Efectivo Anual
		double costoEfectivo = 0.0;
		CostoEfectivoAnual costoEfectivoAnual = new CostoEfectivoAnual(); 
		costoEfectivo = costoEfectivoAnual.CalculoCostoEfectivo(
				tasaEfectivaAnual
				,yearPago,monthPago,dayPago 
				,plazoPago
				,diaPagoSel
				,mesesGracia
				,dobleJulio
				,dobleDiciembre
				, calculoCuota);
		
		Hashtable dataCalculoCuota = new Hashtable();
		dataCalculoCuota.put("calculoCuota",calculoCuota);
		dataCalculoCuota.put("costoEfectivo",new Double(costoEfectivo));
		return dataCalculoCuota;
		
		
	}
	
	private ArrayList CalculoPrestamoBase(
			double cuotaIni
			,double comisionEvaluacion 
			,double tasaEfectivaAnual
			,int yearPago, int monthPago, int dayPago 
			,double tasaSegDesgravMensual
			,double valorInmueble
			,double tasaSegInmuebleMensual
			,int plazoPago
			,double portes
			,int diaPagoSel
			,int mesesGracia
			,int dobleJulio
			,int dobleDiciembre
			,int finanGraciaAgente
			){
		
		double saldoInicial = 0.0;
		
		ArrayList cuotaFinal = null;

	    ResourceBundle rb = ResourceBundle.getBundle("parametro");
	    String calcInmubFijo = rb.getString("calcInmubFijo");
		
		saldoInicial = ObtenerSaldoInicial(
			cuotaIni 
			,comisionEvaluacion
			,tasaEfectivaAnual
			,yearPago,monthPago,dayPago
			,tasaSegDesgravMensual
			,valorInmueble
			,tasaSegInmuebleMensual
			,plazoPago
			,portes
			,diaPagoSel
			,calcInmubFijo);
		
		//Hallando la cuota con el saldo Inicial Calculado
		if (saldoInicial > 0){
			ArrayList cuotaCromo = null;
			CalculoCuotaHipotecario cuotaCromogram = new CalculoCuotaHipotecario();
			cuotaCromo = cuotaCromogram.CalculoBaseCuota(
					saldoInicial
					,comisionEvaluacion
					,tasaEfectivaAnual
					,yearPago, monthPago, dayPago 
					,tasaSegDesgravMensual
					,valorInmueble
					,tasaSegInmuebleMensual
					,plazoPago
					,portes
					,diaPagoSel
					,mesesGracia
					,dobleJulio
					,dobleDiciembre
					,finanGraciaAgente);

			Amortizacion montoCuotaFinal = null;
			int registros = cuotaCromo.size()-1;
			montoCuotaFinal = (Amortizacion)cuotaCromo.get(registros);
			double cuotaAprox = montoCuotaFinal.getCuotaTemporal();

			double diferencia = Util.redondeoDouble(cuotaIni 
						- cuotaAprox,Util.NUM_DIGITOS_DECIMAL_2);
			
			diferencia = Math.abs(diferencia);
			double desvSaldo = Util.redondeoDouble(
					(cuotaIni * saldoInicial) 
					/ cuotaAprox,Util.NUM_DIGITOS_DECIMAL_2);
			
			double errorVarianza = 0.0;
			int iterar = 1;

			do {
				
				ArrayList arrCuotaItera = null;
				
				
				arrCuotaItera = cuotaCromogram.CalculoBaseCuota(
						desvSaldo
						,comisionEvaluacion
						,tasaEfectivaAnual
						,yearPago, monthPago, dayPago 
						,tasaSegDesgravMensual
						,valorInmueble
						,tasaSegInmuebleMensual
						,plazoPago
						,portes
						,diaPagoSel
						,mesesGracia
						,dobleJulio
						,dobleDiciembre
						,finanGraciaAgente);

				cuotaFinal = null;
				cuotaFinal = Util.copyArray(arrCuotaItera);
				
				Amortizacion amortItera = null;
				int registrosItera = cuotaCromo.size()-1;
				amortItera = (Amortizacion)arrCuotaItera.get(registrosItera);
				double cuotaAproxItera = 0.0;
				cuotaAproxItera = amortItera.getCuotaTemporal();
				
				//Obteniendo el monto promedio de desviacion de la amortizacion
				desvSaldo = Util.redondeoDouble((cuotaIni * desvSaldo) 
						/ cuotaAproxItera,Util.NUM_DIGITOS_DECIMAL_2);
				errorVarianza = diferencia;
				//calculando la difeencia
				diferencia = Util.redondeoDouble(cuotaIni 
						- cuotaAproxItera,Util.NUM_DIGITOS_DECIMAL_2);
				diferencia = Math.abs(diferencia);
				iterar ++;
				
			}while(diferencia > Util.ERROR_DESVIACION 
					&& iterar <= Util.NUMERO_CORRIDAS
					&& errorVarianza != diferencia);

		}

		
		
		return cuotaFinal;
	}
	
	
	public double ObtenerSaldoInicial(
			double cuotaIni 
			,double comisionEvaluacion
			,double tasaEfectivaAnual
			,int yearPago,int monthPago,int dayPago
			,double tasaSegDesgravMensual
			,double valorInmueble
			,double tasaSegInmuebleMensual
			,int plazoPago
			,double portes
			,int diaPagoSel
			,String ValInmubFijo){
	
		double interesesSeguro[] = new double[3];
		double saldoIni = 0.0;
		
		Calendar fechaInicio = Calendar.getInstance();
		fechaInicio.set(yearPago,monthPago,dayPago);
		
		BNDate bnFecha =  new BNDate(); 
        bnFecha.setFecha(fechaInicio);
        
		bnFecha = Util.obtenerPeriodoSiguiente(bnFecha.getFecha(),diaPagoSel);
        
		interesesSeguro = Util.CalculoInteresesSeguro(
				tasaEfectivaAnual
				,bnFecha.getPeriodo()
				,tasaSegDesgravMensual
				,tasaSegInmuebleMensual
				,valorInmueble
				,ValInmubFijo);
		
		double interesCuota = 0.0;
		
		interesCuota = Util.CalculoCuota(
				interesesSeguro[0]
				,plazoPago);
		
		saldoIni = Util.redondeoDouble(((cuotaIni - 
					(interesesSeguro[2] 
					 + portes))
					/ (interesCuota
					 +interesesSeguro[1])),Util.NUM_DIGITOS_DECIMAL_2);
		
		return Util.redondeoDouble(saldoIni - comisionEvaluacion,Util.NUM_DIGITOS_DECIMAL_2);
	}

	
	

	
}
